#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

//链接：https://www.acwing.com/problem/content/3273/

//由于最小生成树算法，不仅可以求出最小生成树，同时，所求出的树，
//具有最大的边的权重在所有生成树里面最小的性质，所以，此题直接用最小生成树算法即可
//此处选用Kruskal算法

const int N = 50010,M = 100010;

int n,m;

//用结构体存边
struct Edge{
    int a,b,c;
    bool operator < (const Edge & temp) const{
        return c < temp.c;
    }
}edge[M];

//kruskal算法需要用到并查集
int p[N];

int find(int x){
    if (p[x] != x)p[x] = find(p[x]);
    return p[x];
}

int main(){
    int noUseful;
    scanf("%d%d%d",&n,&m,&noUseful);
    //初始化每个点的父节点为自己
    for (int i = 1; i <= n; i++)p[i] = i;
    //读入每条边
    for (int i = 0; i < m; i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        edge[i] = {a,b,c};
    }

    //Kruskal算法需要对所有边按照权重进行从小到大排序
    sort(edge,edge + m);

    int res = 0;
    //对每条边加入最小生成树中
    for (int i =0; i < m; i ++){
        int a = edge[i].a, b = edge[i].b, c = edge[i].c;
        if (find(a) != find(b)){
            p[find(a)] = find(b);
            //因为已经排好序，所以，最后一次加入的边，权重一定最大
            res = c;
        }
    }
    cout << res;

    return 0;
}